import { Inject, Provide } from '@midwayjs/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository, Not, In } from 'typeorm';
import { TypeORMDataSourceManager } from '@midwayjs/typeorm';

import { Permission } from '../entity/permission.entity';
import { RolePermission } from '../entity/role-permission.entity';

import { Role } from '../entity/role.entity';

@Provide()
export class RoleService {
    @InjectEntityModel(Role)
    roleModel: Repository<Role>;

    @InjectEntityModel(Permission)
    permissionModel: Repository<Permission>;

    @InjectEntityModel(RolePermission)
    rolePermissionModel: Repository<RolePermission>;

    @Inject()
    dataSourceManager: TypeORMDataSourceManager;
  
    constructor() {}

    /**
     * 创建角色
     */
    async create(role: Partial<Role>): Promise<Role> {
        // 检查角色名称是否存在
        const existRole = await this.roleModel.findOne({
            where: { roleName: role.roleName }
        });
        if (existRole) {
            throw new Error('角色名称已存在');
        }

        // 检查角色标识是否存在
        const existRoleKey = await this.roleModel.findOne({
            where: { roleCode: role.roleCode }
        });
        if (existRoleKey) {
            throw new Error('角色标识已存在');
        }

        const newRole = this.roleModel.create(role);
        return await this.roleModel.save(newRole);
    }

    /**
     * 更新角色
     */
    async update(id: number, role: Partial<Role>): Promise<boolean> {
        if (role.roleName) {
            const existRole = await this.roleModel.findOne({
                where: { roleName: role.roleName, id: Not(id) }
            });
            if (existRole) {
                throw new Error('角色名称已存在');
            }
        }

        if (role.roleCode) {
            const existRoleKey = await this.roleModel.findOne({
                where: { roleCode: role.roleCode, id: Not(id) }
            });
            if (existRoleKey) {
                throw new Error('角色标识已存在');
            }
        }

        const result = await this.roleModel.update(id, role);
        return result.affected > 0;
    }

    /**
     * 删除角色（软删除）
     */
    async delete(id: number): Promise<boolean> {
        const result = await this.roleModel.update(id, {
            delFlag: 1,
            updateTime: new Date()
        });
        return result.affected > 0;
    }

    /**
     * 获取角色信息
     */
    async getInfo(id: number): Promise<Role> {
        return await this.roleModel.findOne({
            where: { id, delFlag: 0 }
        });
    }

    /**
     * 获取角色列表
     */
    async getList(params: {
        page?: number;
        pageSize?: number;
        roleName?: string;
        roleKey?: string;
        status?: number;
    }): Promise<[Role[], number]> {
        const { page = 1, pageSize = 10, roleName, roleKey, status } = params;

        const queryBuilder = this.roleModel.createQueryBuilder('role')
            .where('role.delFlag = :delFlag', { delFlag: 0 });

        if (roleName) {
            queryBuilder.andWhere('role.roleName LIKE :roleName', {
                roleName: `%${roleName}%`
            });
        }

        if (roleKey) {
            queryBuilder.andWhere('role.roleCode LIKE :roleCode', {
                roleCode: `%${roleKey}%`
            });
        }

        if (status !== undefined) {
            queryBuilder.andWhere('role.status = :status', { status });
        }

        return await queryBuilder
            .skip((page - 1) * pageSize)
            .take(pageSize)
            .orderBy('role.roleSort', 'ASC')
            .getManyAndCount();
    }

    /**
     * 为角色分配权限
     * @param roleId 角色ID
     * @param permIds 权限ID数组
     */
    async assignPermissions(roleId: number, permIds: number[]): Promise<boolean> {
        // 检查角色是否存在
        const role = await this.roleModel.findOne({
            where: { id: roleId, delFlag: 0 }
        });
        if (!role) {
            throw new Error('角色不存在');
        }

        // 检查权限是否存在
        const permissions = await this.permissionModel.find({
            where: { id: In(permIds), delFlag: 0 }
        });
        if (permissions.length !== permIds.length) {
            throw new Error('部分权限不存在');
        }

        // 使用事务确保数据一致性
        const dataSource = this.dataSourceManager.getDataSource('default');
        const queryRunner = dataSource.createQueryRunner();
        await queryRunner.connect();
        await queryRunner.startTransaction();

        try {
            // 先删除该角色的所有权限
            await this.rolePermissionModel.delete({ roleId });

            // 添加新的权限关联
            const rolePermissions = permIds.map(permId => {
                const rolePermission = new RolePermission();
                rolePermission.roleId = roleId;
                rolePermission.permId = permId;
                return rolePermission;
            });

            await this.rolePermissionModel.save(rolePermissions);
            await queryRunner.commitTransaction();
            return true;
        } catch (error) {
            await queryRunner.rollbackTransaction();
            throw error;
        } finally {
            await queryRunner.release();
        }
    }

    /**
     * 获取角色已分配的权限
     * @param roleId 角色ID
     */
    async getRolePermissions(roleId: number): Promise<Permission[]> {
        // 检查角色是否存在
        const role = await this.roleModel.findOne({
            where: { id: roleId, delFlag: 0 }
        });
        if (!role) {
            throw new Error('角色不存在');
        }

        // 获取角色权限关联
        const roleWithPermissions = await this.roleModel.findOne({
            where: { id: roleId, delFlag: 0 },
            relations: ['permissions']
        });

        return roleWithPermissions.permissions || [];
    }

    /**
     * 移除角色的权限
     * @param roleId 角色ID
     * @param permIds 权限ID数组
     */
    async removePermissions(roleId: number, permIds: number[]): Promise<boolean> {
        // 检查角色是否存在
        const role = await this.roleModel.findOne({
            where: { id: roleId, delFlag: 0 }
        });
        if (!role) {
            throw new Error('角色不存在');
        }

        // 使用事务确保数据一致性
        const dataSource = this.dataSourceManager.getDataSource('default');
        const queryRunner = dataSource.createQueryRunner();
        await queryRunner.connect();
        await queryRunner.startTransaction();

        try {
            // 删除指定的权限关联
            await this.rolePermissionModel.delete({
                roleId,
                permId: In(permIds)
            });
            
            await queryRunner.commitTransaction();
            return true;
        } catch (error) {
            await queryRunner.rollbackTransaction();
            throw error;
        } finally {
            await queryRunner.release();
        }
    }
}